<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ES6类</title>
</head>
<body>
  <script>
    /* 
    需求: 
      现在2个人, 都有姓名与年龄(值自己指定), 都能自我介绍自己的姓名和年龄
      现在又有了一个学生, 它有身价的属性, 能介绍它的所有信息
    */

    /* 
    ES6类的语法结构
      构造器: 用来初始化实例的属性
      实例属性
        在构造器中: this.propName = 非函数值
        在类体中: propName = 非函数值
      实例方法
        在构造器中: this.propName = 函数值
        在类体中: propName = 函数值
          function函数  propName = function () {}   this是实例/undefined
          箭头函数 propName = () => {} this永远是实例 (用的是构造器的this)
      原型方法:  原型对象上的方法
        在类体中: xxx () {}
      静态属性: 类上
        在类体中:  static propName = 非函数值
      静态方法: 类上
        在类体中:  static propName = 函数值

      class默认开启严格模式

      继承: extends / super
    */

    class Person {

      // 静态属性/方法
      static test5 = 'atguigu...'
      static test6 = function () {
        console.log('test6')
      }

      constructor (name, age) {
        this.name = name
        this.age = age
        this.test = function () {
          console.log('test')
        }

        /* 本质还是在constructor中执行的 */
       /*  this.test2 = 'atguigu'
        this.test3 = function () {
          console.log('test3')
        }
        this.test4 = () => {
          console.log('test4')
        } */
      }

      // 添加一个实例属性  ES6开始都不支持 => ES2015后来新语法才支持这种形式
      test2 = 'atguigu'
      // 添加一个实例方法
      test3 = function () {
        console.log('test3', this) // p  => 因为是通过p来调用的
      }
      test4 = () => {
        console.log('test4', this) // p => 箭头函数本质上是在构造器中定义的, 用它的this
      }

      // 原型方法(原型对象上的方法)
      sayInfo () {
        console.log(`我叫${this.name}, 今年${this.age}`)
      }
    }

    // const p = new Person('大强', 23)
    // console.log(p)
    // p.sayInfo()
    // p.test3() // p
    // p.test4() // 

    // Person.test6()

    // const fn1 = p.test3
    // const fn2 = p.test4
    // fn1()
    // fn2()

    /* 
    现在又有了一个学生, 它有身价的属性, 能介绍它的所有信息
    */
    class Student extends Person {
      constructor (name, age, price) {
        // 调用父类型构造器, 来初始化子类实例的属性
        super(name, age)
        this.price = price
      }
      // 重写从父类继承的方法
      sayInfo () {
        console.log(`我叫${this.name}, 今年${this.age}, 月入${this.price}`)
      }
    }

    const s = new Student('tom', 23, 15000)
    console.log(s.name, s.age, s.price)
    s.sayInfo()
    console.log(s)
  </script>
</body>
</html>